/*
下载管理
文档位置
http://www.html5plus.org/doc/zh_cn/downloader.html
全局监听器 getApp().globalData._listenInter 

onLoad() {
    that=this;
    uni.$on('downloadUpdate', this.downloadUpdate)
    // uni.$on('onStateChanged', this.onStateChanged)
    qDownload = new Download();
    this.list = qDownload.list;
    this.DownloadState = qDownload.DownloadState;
    qDownload.openListener();
},
 onUnload(){
        that=null
        // uni.$off('onStateChanged', this.onStateChanged)
        uni.$off('downloadUpdate', this.downloadUpdate)
        qDownload.closeListener();
    },
    
downloadUpdate({list,length,ingNum,compNum}){
      this.list = Object.assign({},list);
},

// 下载
async addDown(){
      const dtask =  qDownload.create('http://weiquang.zhilongtech.com/test.mp3',true);
      let data =  qDownload.normali({},dtask);
       console.log("data" + JSON.stringify(data));
      qDownload.add(data);
       this.list = Object.assign({}, qDownload.list)
    },
//暂停下载 继续下载 播放视频
select(data){
    if(data.state==4){
       uni.navigateTo({
           url: `/pages/base/video?path=${data.filename}`,
              // url: `/pages/base/video2?path=${data.filename}`,
           success: res => {},
           fail: (err) => {
               console.log("err: " + JSON.stringify(err));
           },
           complete: () => {}
       });
    } else if(data.state==5){
        qDownload.resume(data.id,data.dindex)
    } else{
        qDownload.pause(data.id,data.dindex)
    }
},

视频播放要转绝对路径
plus.io.convertLocalFileSystemURL(path)
<video id="myVideo" class="video" v-if="src.length" :httpCache="true" :src="src" autoplay  @error="videoErrorCallback" controls></video>

*/
const DownloadState = {
    undefined: '未开始', //通过plus.downloader.createDownload()方法创建下载任务后的初始状态，此时可调用其start()方法开始下载。
    '0': '开始调度', //下载任务开始调度，调用下载任务的start()方法之后处于此状态，此时下载任务处于可调度下载状态。
    '1': '开始请求', //下载任务开始请求，下载任务建立网络连接，发送请求到服务器并等待服务器的响应。
    '2': '请求已经接收', //下载任务请求已经接收，下载任务网络连接已建立，服务器返回响应，准备传输数据内容。
    '3': '接收数据', //下载任务接收数据，监听statechanged事件时可多次触发此状态。
    '4': '已完成', //下载任务已完成，下载任务完成数据传输并断开连接，下载成功或失败都会设置为此状态。
    '5': '已暂停', //下载任务已暂停，调用下载任务的pause()方法将任务暂停，此时可调用其resume()方法重新开始下载。
    '-1': '枚举任务状态', //非下载任务状态，泛指所有下载任务的状态，用于enumerate()和clear()操作时指定作用于所有下载任务。
};
export default class Download {
    constructor(arg = {}) {
        this.storageName = arg.storageName || 'downList'; //下载缓存
        this._filename = '_downloads/uniapp/'; //下载路径
        this.list = {};
        this.DownloadState = DownloadState;
        this._init();
    }
    _init() {
        this.list = this.getData();
    }
    /*获取下载缓存列表*/
    getData() {
        return uni.getStorageSync(this.storageName) || {};
    }
    setData(list, updata = true) {
        uni.setStorageSync(this.storageName, list);
        if (updata) this.list = list;
    }
    async getNetworkType() {
        const [err, res] = await uni.getNetworkType();
        return new Promise((qres, qrej) => {
            if (res.networkType == null) {
                uni.showToast({
                    title: `当前没有网络！`,
                    icon: 'none'
                })
                qres(res.networkType)
            } else if (res.networkType != 'wifi') {
                uni.showToast({
                    title: `当前网络是${res.networkType}，下载视频会产生大量流量！`,
                    icon: 'none'
                })
                qres(res.networkType)
            } else {
                qres(res.networkType)
            }
        })
    }
    //新建下载
    create(url, start = true) {
        const dtask = plus.downloader.createDownload(url, {
            filename: this._filename,
        });
        if (start) {
            dtask.start();
            // dtask.addEventListener("statechanged", throttle(this.onStateChanged,1000,{trailing:true}),false)
        }
        this.openListener();
        return dtask
    }
    add(data) {
        this.list[data.id] = data;
        this.setData(this.list, false)
    }
    remove(data, callback = null) {
        delete this.list[data.id];
        this.setData(this.list, false);
        console.log(this.list)
        callback && callback(this.list)
    }
    //下载监听回调
    onStateChanged(download, status) {
        /*发射全局事件*/
        uni.$emit('onStateChanged', {
            download,
            status,
        })
    }
    //全部任务开始
    async startAll() {
        const [err, res] = await uni.getNetworkType();
        if (res.networkType == null) {
            uni.showToast({
                title: `当前没有网络！`,
                icon: 'none'
            })
            return
        } else if (res.networkType != 'wifi') {
            uni.showToast({
                title: `当前网络是${res.networkType}，下载视频会产生大量流量！`,
                icon: 'none'
            })
            return
        }
        console.log('startAll')
        plus.downloader.startAll();
        this.openListener();
    }
    //全部任务暂停
    pauseAll() {
        console.log('pauseAll')
        plus.downloader.enumerate(downloads => {
            for (let i = 0, l = downloads.length; i < l; i++) {
                let dtask = downloads[i];
                if (dtask.state != 4 && dtask.state != 5) {
                    console.log(dtask)
                    dtask.pause()
                }
            }
            setTimeout(() => {
                this.allUpdate({
                    speed: false
                })
            }, 1000)
        }, -1);
    }
    //暂停下载
    async pause(id, index) {
        console.log('pause')
        const dtask = await this.byId(id, index);
        dtask.pause();
        // this.list[dtask].state = 5
        this.openListener();
        // setTimeout(()=>{
        //     this.allUpdate({speed:false})
        // },1000)
    }
    async resume(id, index) {
        console.log('resume')
        const dtask = await this.byId(id, index);
        console.log(dtask)
        dtask.resume();
        this.openListener();
    }
    /*
    全部更新 用户计算器或者手动
    speed与上一秒的下载速度
    emit是否发射全局事件
    */
    allUpdate(opt = {}, callback = null) {
        opt = Object.assign({
            speed: true,
            emit: true,
        }, opt)
        let length;
        let ingNum = 0;
        let compNum = 0;
        plus.downloader.enumerate(downloads => {
            length = downloads.length;
            // console.log('length', length)
            if (length == 0) {
                this.closeListener();
                return
            }
            for (let i = 0, l = downloads.length; i < l; i++) {
                const download = downloads[i];
                //不存在退出当前循环
                if (!this.list[download.id]) continue;
                if (download.state == 4) {
                    compNum++
                }
                if (this.list[download.id].state != 4) {
                    this.list[download.id].dindex = i;
                    this.list[download.id].downloadedSizeName = this.getFileSize(download.downloadedSize);
                    this.list[download.id].percent = this.getPercent(download.downloadedSize, download
                        .totalSize);
                    this.list[download.id].state = download.state;
                    this.list[download.id].totalSizeName = this.getFileSize(download.totalSize);
                    if (opt.speed) {
                        this.list[download.id].speed = this.getFileSize(download.downloadedSize - this.list[
                            download.id].downloadedSize);
                    }
                    this.list[download.id].downloadedSize = download.downloadedSize;
                    this.list[download.id].filename = download.filename; //文件名
                }

            }
            this.setData(this.list, false);
            if (opt.emit) {
                uni.$emit('downloadUpdate', {
                    list: this.list,
                    length,
                    ingNum: length - compNum,
                    compNum,
                })
            }
            if (callback && typeof callback == 'function') {
                callback(this.list)
            }
        }, -1)
    }
    //打开监听器
    openListener() {
        console.log('打开监听器openListener')
        if (getApp().globalData._listenInter) return;
        getApp().globalData._listenInter = setInterval(() => {
            this.allUpdate.call(this);
        }, 1000)
    }
    //关闭监听器
    closeListener() {
        console.log('关闭监听器closeListener')
        if (getApp().globalData._listenInter) {
            clearInterval(getApp().globalData._listenInter);
            getApp().globalData._listenInter = null;
        }
    }
    clear() {
        plus.downloader.clear(-1);
        this.setData({});
    }
    /*获取下载数量*/
    async getLength() {
        return new Promise((res, rej) => {
            res(Object.keys(this.list).length)
            // plus.downloader.enumerate(function(downloads) {
            //     res(downloads.length)
            // }, -1);
            // this.list
        })
    }
    /*查找id*/
    async byId(id, index = null, state = -1) {
        return new Promise((res, rej) => {
            plus.downloader.enumerate(function(downloads) {
                if (index != null && downloads[index].id == id) {
                    res(downloads[index])
                    return
                }
                for (let i = 0, l = downloads.length; i < l; i++) {
                    if (downloads[i].id == id) {
                        let dtask = downloads[i];
                        dtask.index = i;
                        res(dtask)
                        break;
                    }
                }
                rej(false)
            }, state);
        })
    }

    /*
    添加下载信息
    downloadedSize: 已完成下载文件的大小
    totalSize: 下载任务文件的总大小
    filename： 下载文件路径
    downPath： 下载文件夹
    speed:下载速度/s
    setatName:下载状态名
     setat:下载状态
     percent：百分比
    */
    normali(data, dtask) {
        data.id = dtask.id;
        data.filename = dtask.filename;
        data.downPath = dtask.filename;
        data.totalSize = dtask.totalSize;
        data.totalSizeName = this.getFileSize(dtask.totalSize);
        data.downloadedSizeName = this.getFileSize(dtask.downloadedSize);
        data.downloadedSize = dtask.downloadedSize;
        data.percent = this.getPercent(dtask.downloadedSize, dtask.totalSize);
        data.setatName = DownloadState[dtask.state];
        data.state = dtask.state;
        data.speed = 0;
        return data
    }
    //文件大小转换
    getFileSize(fileByte) {
        var fileSizeByte = fileByte;
        var fileSizeMsg = "";
        if (fileSizeByte < 1048576) fileSizeMsg = (fileSizeByte / 1024).toFixed(2) + "KB";
        else if (fileSizeByte == 1048576) fileSizeMsg = "1MB";
        else if (fileSizeByte > 1048576 && fileSizeByte < 1073741824) fileSizeMsg = (fileSizeByte / (1024 * 1024))
            .toFixed(
                2) + "MB";
        else if (fileSizeByte > 1048576 && fileSizeByte == 1073741824) fileSizeMsg = "1GB";
        else if (fileSizeByte > 1073741824 && fileSizeByte < 1099511627776) fileSizeMsg = (fileSizeByte / (1024 *
            1024 *
            1024)).toFixed(2) + "GB";
        else fileSizeMsg = "文件超过1TB";
        return fileSizeMsg;
    }
    //计算百分比
    getPercent(num, total) {
        num = parseFloat(num);
        total = parseFloat(total);
        if (isNaN(num) || isNaN(total)) {
            return "-";
        }
        //return total <= 0 ? "0%" : (Math.round(num / total * 10000) / 100.00) + "%";
        return total <= 0 ? "0" : (Math.round(num / total * 10000) / 100.00);
    }
}

/*删除文件*/
export function removeFile(path) {
    return new Promise((res, rej) => {
        plus.io.resolveLocalFileSystemURL(path, function(entry) {
            entry.remove(function() {
                res(true)
                console.log(dtask.filename + '删除成功');
            }, function(err) {
                console.log("err: ", err);
                uni.showToast({
                    title: err.message,
                    icon: 'none'
                })
                res(true)
            });
        }, function() {
            console.log('找不到文件，不用删除了')
            res(true)
        });
    })
}






//节流
const throttle = (func, wait, options) => {
    var timeout, context, args, result;
    var previous = 0;
    if (!options) options = {};
    var later = function() {
        previous = options.leading === false ? 0 : +new Date();
        timeout = null;
        result = func.apply(context, args);
        if (!timeout) context = args = null;
    };
    var throttled = function() {
        var now = +new Date();
        if (!previous && options.leading === false) previous = now;
        var remaining = wait - (now - previous);
        context = this;
        args = arguments;
        if (remaining <= 0 || remaining > wait) {
            // console.log('remaining <= 0 || remaining > wait')
            if (timeout) {
                clearTimeout(timeout);
                timeout = null;
            }
            previous = now;
            result = func.apply(context, args);
            if (!timeout) context = args = null;
        } else if (!timeout && options.trailing !== false) {
            timeout = setTimeout(later, remaining);
        }
        return result;
    };
    throttled.cancel = function() {
        clearTimeout(timeout);
        previous = 0;
        timeout = context = args = null;
    };
    return throttled;
}
